package com.derbysoft.synxisadapter.commons.utils;

import org.apache.commons.lang.Validate;
import org.dom4j.Document;
import org.dom4j.io.DocumentSource;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.xml.transform.StringResult;

import javax.xml.bind.helpers.AbstractMarshallerImpl;
import javax.xml.transform.Source;
import java.io.InputStream;
import java.util.HashMap;

public abstract class JaxbUtils {
    private static Logger logger = LoggerFactory.getLogger(JaxbUtils.class);
    public static Object unmarshal(InputStream stream, Jaxb2Marshaller marshaller) {
        try {
            Validate.notNull(stream);
            Validate.notNull(marshaller);
            SAXReader reader = new SAXReader();
            Document document = reader.read(stream);
            Source source = new DocumentSource(document);

            return marshaller.unmarshal(source);
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            throw new IllegalStateException(e.getMessage());
        }
    }

    public static <T> T unmarshall(InputStream stream, Class<T> clazz) {
        return (T) unmarshal(stream, createMarshaller(clazz));
    }


    public static String marshall(Object source, Jaxb2Marshaller marshaller) {
        Validate.notNull(source);
        Validate.notNull(marshaller);

        StringResult stringResult = new StringResult();
        marshaller.marshal(source, stringResult);
        return stringResult.toString();
    }

    public static String marshall(Object source) {
        Jaxb2Marshaller marshaller = createMarshaller(source.getClass());
        return marshall(source, marshaller);
    }

    public static Jaxb2Marshaller createMarshaller(Class clazz) {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        HashMap<String, Object> map = new HashMap<String, Object>();

        map.put(AbstractMarshallerImpl.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setMarshallerProperties(map);
        String contextPath = clazz.getPackage().getName();
        marshaller.setContextPath(contextPath);
        try {
            marshaller.afterPropertiesSet();
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return marshaller;
    }
}
